/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.configuration.event; import java.util.Collection; import junit.framework.TestCase; /** * Test class for EventSource. * * @version $Id: TestEventSource.java 495918 2007-01-13 16:33:02Z oheger $ */ public class TestEventSource extends TestCase { /** Constant for the event type used for testing. */ static final int TEST_TYPE = 42; /** Constant for the event property name. */ static final String TEST_PROPNAME = "test.property.name"; /** Constant for the event property value. */ static final Object TEST_PROPVALUE = "a test property value"; /** The object under test. */ CountingEventSource source; protected void setUp() throws Exception { super.setUp(); source = new CountingEventSource(); } /** * Tests a newly created source object. */ public void testInit() { assertTrue("Listeners list is not empty", source .getConfigurationListeners().isEmpty()); assertFalse("Removing listener", source .removeConfigurationListener(new TestListener())); assertFalse("Detail events are enabled", source.isDetailEvents()); assertTrue("Error listeners list is not empty", source .getErrorListeners().isEmpty()); } /** * Tests registering a new listener. */ public void testAddConfigurationListener() { TestListener l = new TestListener(); source.addConfigurationListener(l); Collection listeners = source.getConfigurationListeners(); assertEquals("Wrong number of listeners", 1, listeners.size()); assertTrue("Listener not in list", listeners.contains(l)); } /** * Tests adding an undefined configuration listener. This should cause an * exception. */ public void testAddNullConfigurationListener() { try { source.addConfigurationListener(null); fail("Could add null listener!"); } catch (IllegalArgumentException iex) { // ok } } /** * Tests removing a listener. */ public void testRemoveConfigurationListener() { TestListener l = new TestListener(); assertFalse("Listener can be removed?", source .removeConfigurationListener(l)); source.addConfigurationListener(l); source.addConfigurationListener(new TestListener()); assertFalse("Unknown listener can be removed", source .removeConfigurationListener(new TestListener())); assertTrue("Could not remove listener", source .removeConfigurationListener(l)); assertFalse("Listener still in list", source .getConfigurationListeners().contains(l)); } /** * Tests if a null listener can be removed. This should be a no-op. */ public void testRemoveNullConfigurationListener() { source.addConfigurationListener(new TestListener()); assertFalse("Null listener can be removed", source .removeConfigurationListener(null)); assertEquals("Listener list was modified", 1, source .getConfigurationListeners().size()); } /** * Tests whether the listeners list is read only. */ public void testGetConfigurationListenersUpdate() { source.addConfigurationListener(new TestListener()); Collection list = source.getConfigurationListeners(); try { list.add("test"); fail("Could manipulate list!"); } catch (Exception ex) { // ok } } /** * Tests that the collection returned by getConfigurationListeners() is * really a snapshot. A later added listener must not be visible. */ public void testGetConfigurationListenersAddNew() { Collection list = source.getConfigurationListeners(); source.addConfigurationListener(new TestListener()); assertTrue("Listener snapshot not empty", list.isEmpty()); } /** * Tests enabling and disabling the detail events flag. */ public void testSetDetailEvents() { source.setDetailEvents(true); assertTrue("Detail events are disabled", source.isDetailEvents()); source.setDetailEvents(true); source.setDetailEvents(false); assertTrue("Detail events are disabled again", source.isDetailEvents()); source.setDetailEvents(false); assertFalse("Detail events are still enabled", source.isDetailEvents()); } /** * Tests delivering an event to a listener. */ public void testFireEvent() { TestListener l = new TestListener(); source.addConfigurationListener(l); source.fireEvent(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, true); assertEquals("Not 1 event created", 1, source.eventCount); assertEquals("Listener not called once", 1, l.numberOfCalls); assertEquals("Wrong event type", TEST_TYPE, l.lastEvent.getType()); assertEquals("Wrong property name", TEST_PROPNAME, l.lastEvent .getPropertyName()); assertEquals("Wrong property value", TEST_PROPVALUE, l.lastEvent .getPropertyValue()); assertTrue("Wrong before event flag", l.lastEvent.isBeforeUpdate()); } /** * Tests firering an event if there are no listeners. */ public void testFireEventNoListeners() { source.fireEvent(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, false); assertEquals("An event object was created", 0, source.eventCount); } /** * Tests generating a detail event if detail events are not allowed. */ public void testFireEventNoDetails() { TestListener l = new TestListener(); source.addConfigurationListener(l); source.setDetailEvents(false); source.fireEvent(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, false); assertEquals("Event object was created", 0, source.eventCount); assertEquals("Listener was called", 0, l.numberOfCalls); } /** * Tests whether an event listener can deregister itself in reaction of a * delivered event. */ public void testRemoveListenerInFireEvent() { ConfigurationListener lstRemove = new ConfigurationListener() { public void configurationChanged(ConfigurationEvent event) { source.removeConfigurationListener(this); } }; source.addConfigurationListener(lstRemove); TestListener l = new TestListener(); source.addConfigurationListener(l); source.fireEvent(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, false); assertEquals("Listener was not called", 1, l.numberOfCalls); assertEquals("Listener was not removed", 1, source .getConfigurationListeners().size()); } /** * Tests registering a new error listener. */ public void testAddErrorListener() { TestListener l = new TestListener(); source.addErrorListener(l); Collection listeners = source.getErrorListeners(); assertEquals("Wrong number of listeners", 1, listeners.size()); assertTrue("Listener not in list", listeners.contains(l)); } /** * Tests adding an undefined error listener. This should cause an exception. */ public void testAddNullErrorListener() { try { source.addErrorListener(null); fail("Could add null error listener!"); } catch (IllegalArgumentException iex) { // ok } } /** * Tests removing an error listener. */ public void testRemoveErrorListener() { TestListener l = new TestListener(); assertFalse("Listener can be removed?", source.removeErrorListener(l)); source.addErrorListener(l); source.addErrorListener(new TestListener()); assertFalse("Unknown listener can be removed", source .removeErrorListener(new TestListener())); assertTrue("Could not remove listener", source.removeErrorListener(l)); assertFalse("Listener still in list", source.getErrorListeners() .contains(l)); } /** * Tests if a null error listener can be removed. This should be a no-op. */ public void testRemoveNullErrorListener() { source.addErrorListener(new TestListener()); assertFalse("Null listener can be removed", source .removeErrorListener(null)); assertEquals("Listener list was modified", 1, source .getErrorListeners().size()); } /** * Tests whether the listeners list is read only. */ public void testGetErrorListenersUpdate() { source.addErrorListener(new TestListener()); Collection list = source.getErrorListeners(); try { list.add("test"); fail("Could manipulate list!"); } catch (Exception ex) { // ok } } /** * Tests delivering an error event to a listener. */ public void testFireError() { TestListener l = new TestListener(); source.addErrorListener(l); Exception testException = new Exception("A test"); source.fireError(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, testException); assertEquals("Not 1 event created", 1, source.errorCount); assertEquals("Error listener not called once", 1, l.numberOfErrors); assertEquals("Normal event was generated", 0, l.numberOfCalls); assertEquals("Wrong event type", TEST_TYPE, l.lastEvent.getType()); assertEquals("Wrong property name", TEST_PROPNAME, l.lastEvent .getPropertyName()); assertEquals("Wrong property value", TEST_PROPVALUE, l.lastEvent .getPropertyValue()); assertEquals("Wrong Throwable object", testException, ((ConfigurationErrorEvent) l.lastEvent).getCause()); } /** * Tests firering an error event if there are no error listeners. */ public void testFireErrorNoListeners() { source.fireError(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, new Exception()); assertEquals("An error event object was created", 0, source.errorCount); } /** * Tests cloning an event source object. The registered listeners should not * be registered at the clone. */ public void testClone() throws CloneNotSupportedException { source.addConfigurationListener(new TestListener()); source.addErrorListener(new TestListener()); EventSource copy = (EventSource) source.clone(); assertTrue("Configuration listeners registered for clone", copy .getConfigurationListeners().isEmpty()); assertTrue("Error listeners registered for clone", copy .getErrorListeners().isEmpty()); } /** * A test event listener implementation. */ static class TestListener implements ConfigurationListener, ConfigurationErrorListener { ConfigurationEvent lastEvent; int numberOfCalls; int numberOfErrors; public void configurationChanged(ConfigurationEvent event) { lastEvent = event; numberOfCalls++; } public void configurationError(ConfigurationErrorEvent event) { lastEvent = event; numberOfErrors++; } } /** * A specialized event source implementation that counts the number of * created event objects. It is used to test whether the * <code>fireEvent()</code> methods only creates event objects if * necessary. It also allows testing the clone() operation. */ static class CountingEventSource extends EventSource implements Cloneable { int eventCount; int errorCount; protected ConfigurationEvent createEvent(int type, String propName, Object propValue, boolean before) { eventCount++; return super.createEvent(type, propName, propValue, before); } protected ConfigurationErrorEvent createErrorEvent(int type, String propName, Object value, Throwable ex) { errorCount++; return super.createErrorEvent(type, propName, value, ex); } } }